package server

import (
	"errors"
	"log"

	"rtsp1/source/command"
	"rtsp1/source/list"
)

const (
	PATH = "videos"
	PORT = "8554"
)

type Reply struct {
	Address string
	Pid     int
}

type Server struct {
	// cmd     command.Command
	cmd     command.VLC
	pids    list.PidList
	source  list.SourceList
	playing list.PlayList
}

func NewServer() (s *Server) {
	s = new(Server)
	s.cmd = command.NewVLC()
	s.pids = list.NewPidList()
	s.source = list.NewSourceList(PATH)
	s.playing = list.NewPlayList()
	return
}

func (s *Server) GetList(n int, l *[]string) error {
	sl := s.source
	length := len(sl.List)
	if n > 0 && n > length {
		return errors.New("Index bigger than length")
	}
	sourceList := make([]string, length)
	index := 0
	for k, _ := range sl.List {
		sourceList[index] = k
		index++
	}
	*l = sourceList
	return nil
}

func (s *Server) Open(name string, r *Reply) error {
	nameStr := name
	log.Println("want to open", nameStr)
	if s.playing.IsHave(nameStr) {
		log.Println("the resource have been opened")
		source := s.playing.Get(nameStr)
		r.Address = source.Address
		r.Pid = source.Pid

		s.playing.Add(nameStr, source)
		log.Printf("Now have %d users.", s.playing.Get(nameStr).Count)
	} else if s.source.IsHave(nameStr) {
		log.Println("Not in playing, so look into the source list")
		//构造参数
		path := s.source.Get(nameStr)
		channel := nameStr
		//执行命令
		res, err := s.cmd.Start(path, PORT, channel)
		if err != nil {
			log.Println(err)
			return err
		}

		//将进程信息放到pid列表中
		s.pids.Add(res.Pid, nameStr)
		log.Println("Create new process,pid:", res.Pid)

		//将资源放到正在播放列表
		source := list.Source{
			Address: res.Out,
			Pid:     res.Pid,
			Count:   0,
		}
		s.playing.Add(nameStr, source)

		//将将结果返回给调用者
		*r = Reply{
			Address: res.Out,
			Pid:     res.Pid,
		}
		return nil
	} else {
		log.Println("Can't find the resource by the name ", nameStr)
		return errors.New("Can find resource!")
	}
	return nil
}

func (s *Server) Close(pid int, feedback *string) error {
	pidInt := pid
	success := "Success"
	fail := "Can't find the resource"
	log.Println("Want to close source by pid", pidInt)
	if s.pids.IsHave(pidInt) {
		name := s.pids.Get(pidInt)
		//从正在播放中删除
		log.Println("remove from the playing")
		count := s.playing.Remove(name)
		log.Println("Now have", count)
		//如果使用者人数为零，则关掉这个进程
		if count <= 0 {
			err := s.cmd.Stop(pidInt)
			if err != nil {
				return err
			}
			//从pid列表中删除
			s.pids.Remove(pidInt)
		}
		*feedback = success
	} else {
		*feedback = fail
		log.Println("Find no proccess on the server by pid", pidInt)
		return errors.New("Can't finde the resource")
	}
	return nil
}
